package thread;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 验证CAS在某些场景中的效率低于加锁。
 * 也就是乐观锁在某些情况下不如悲观锁。
 * 可以看到：当线程数量越来越大的时候，它们二者的比值在逐渐接近。【而且这还是在需要很多次加锁解锁的情况比较的】。
 * 线程数量 20w个，循环 1000次：
 *      结果为：200000000，时间为：16461      -- 悲观锁
 *      结果为：200000000，时间为：8727      -- 乐观锁
 * 线程数量10个，循环1000w次：
 *      结果为：100000000，时间为：8097      -- 悲观锁
 *      结果为：100000000，时间为：2398      -- 乐观锁
 *
 */
public class CASTest {

    static int threadNum = 200000;

    static int sumNum = 1000;

    //悲观锁的求和
    static int sum = 0;

    //乐观锁的求和
    static AtomicInteger sum1 = new AtomicInteger(0);

    public static void main(String[] args) throws InterruptedException {
        CountDownLatch c = new CountDownLatch(threadNum);
        long start = System.currentTimeMillis();
        test1(c);
        c.await();
        long end = System.currentTimeMillis();
        System.out.println("结果为："+sum+"，时间为："+(end-start));

        CountDownLatch d = new CountDownLatch(threadNum);
        long start1 = System.currentTimeMillis();
        test2(d);
        d.await();
        long end1 = System.currentTimeMillis();
        System.out.println("结果为："+sum1.get()+"，时间为："+(end1-start1));

    }

    //20个线程，分别对sum进行累加操作，1w次
    private static void test1(CountDownLatch c){
        for (int i = 0; i < threadNum; i++) {
            new Thread(){
                @Override
                public void run() {
                    for (int j = 0; j < sumNum ; j++) {
                        synchronized (CASTest.class){
                            sum++;
                        }
                    }
                c.countDown();
                }
            }.start();
        }

    }

    //20个线程，分别对sum1进行累加操作，1w次
    private static void test2(CountDownLatch c){
        for (int i = 0; i < threadNum; i++) {
            new Thread(){
                @Override
                public void run() {
                    for (int j = 0; j < sumNum; j++) {
                        sum1.getAndIncrement();
                    }
                    c.countDown();
                }
            }.start();
        }
    }



}
